import json
import logging
import pathlib
import tomllib
from os import PathLike
from typing import Dict

import yaml

from builtin import exceptions

logger = logging.getLogger(__name__)


def _load_json_file(json_file: str | PathLike[str]):
    """load json file and check file content format

    :param json_file:
    :return:
    """
    with open(json_file, mode='rb') as fp:
        try:
            json_content = json.load(fp)
        except json.JSONDecodeError as e:
            err_msg = f"JSONDecodeError:\nfile: {json_file}\nerror: {e}"
            logger.error(err_msg)
            raise exceptions.FileFormatError

    return json_content


def _load_toml_file(toml_file: str | PathLike[str]) -> Dict:
    """load toml file and check file content format

    :param toml_file:
    :return:
    """
    with open(toml_file, mode='rb') as fp:
        try:
            toml_content = tomllib.load(fp)
        except tomllib.TOMLDecodeError as e:
            err_msg = f"TOMLDecodeError:\nfile: {toml_file}\nerror: {e}"
            logger.error(err_msg)
            raise exceptions.FileFormatError

    return toml_content


def _load_yaml_file(yaml_file: str | PathLike[str]) -> Dict:
    """load yaml file and check file content format

    :param yaml_file:
    :return:
    """
    with open(yaml_file, mode="rb") as stream:
        try:
            yaml_content = yaml.full_load(stream)
        except yaml.YAMLError as e:
            err_msg = f"YAMLError:\nfile: {yaml_file}\nerror: {e}"
            logger.error(err_msg)
            raise exceptions.FileFormatError

        return yaml_content


def load_file(file: str | PathLike[str]) -> Dict:
    """load file content

    :param file:
    :return:
    """
    file = pathlib.Path(file)
    if not file.is_file():
        raise exceptions.FileNotFound(f"file not exists: {file}")

    file_suffix = file.suffix.lower()
    if file_suffix == '.json':
        file_content = _load_json_file(file)
    elif file_suffix == '.toml':
        file_content = _load_toml_file(file)
    elif file_suffix in ['.yml', '.yaml']:
        file_content = _load_yaml_file(file)
    else:
        # '' or other suffix
        raise exceptions.FileFormatError(f"invalid format file: {file}")

    return file_content
